package com.ham.mud;

import java.util.*;

/**
 * Created by hlucas on Jun 17, 2011 at 3:53:12 PM
 */
public class TargetableService {
    public static String findTarget(String search, List<String> searchThroughs) {
        search = search.toLowerCase();
        if(searchThroughs.contains(search)) {
            return search;
        }

        String nearest = findNearestCommandKey(search, searchThroughs);
        if(nearest == null || nearest.equals("-1")) {
            return null;
        }

        return nearest;
    }

    public static Targetable findTarget(String search, List<? extends Targetable>... searchThroughs) {
        search = search.toLowerCase();
        
        Map<String, List<Targetable>> targets = new HashMap<String, List<Targetable>>();

        for(List<? extends Targetable> searchThrough : searchThroughs) {
            for(Targetable targetable : searchThrough) {
                String[] targetingKeys = targetable.getTargetingKeys();
                if(targetingKeys[0].startsWith(search) && targetingKeys.length > 1) {
                    targetingKeys = new String[]{targetingKeys[0]};
                }
                
                for(String targetingKey : targetingKeys) {
                    List<Targetable> targetables = targets.get(targetingKey);
                    if(targetables == null) {
                        targetables = new ArrayList<Targetable>();
                    }
                    targetables.add(targetable);
                    targets.put(targetingKey, targetables);
                }
            }
        }

        if(targets.containsKey(search)) {
            List<Targetable> targetsAtKey = targets.get(search);
            return targetsAtKey.get(0);
        }

        Set<String> keys = targets.keySet();
        String nearestKey = findNearestCommandKey(search, keys);
        if(nearestKey.equals("-1")) return null;

        return targets.get(nearestKey).get(0);
    }

    private static String findNearestCommandKey(String line, Collection<String> keys) {
        if(line == null || line.trim().equals("")) {
            return "-1";
        }

        Set<String> startsWith = getStartsWith(line, keys);
        while(startsWith.size() > 1 && line.length() > 0) {
            startsWith = getStartsWith(line, keys);
            line = line.substring(0, line.length() - 1);
        }

        if(startsWith.size() == 1) {
            return startsWith.iterator().next();
        } else if(startsWith.size() == 0) {
            return "-1";
        }

        return "-1";
    }

    private static Set<String> getStartsWith(String line, Collection<String> keys) {
        Set<String> startsWithList = new HashSet<String>();
        for(String key : keys) {
            if(key.startsWith(line)) {
                startsWithList.add(key);
            }
        }
        return startsWithList;
    }
}
